<html>
 <head>
  <meta charset="utf-8"/>
  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/>
  <title>
   MemCache 超详细解读  | 数螺 | NAUT IDEA
  </title>
  <link href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet"/>
  <link href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
  <style type="text/css">
   #xmain img {
                  max-width: 100%;
                  display: block;
                  margin-top: 10px;
                  margin-bottom: 10px;
                }

                #xmain p {
                    line-height:150%;
                    font-size: 16px;
                    margin-top: 20px;
                }

                #xmain h2 {
                    font-size: 24px;
                }

                #xmain h3 {
                    font-size: 20px;
                }

                #xmain h4 {
                    font-size: 18px;
                }


                .header {
	           background-color: #0099ff;
	           color: #ffffff;
	           margin-bottom: 20px;
	        }

	        .header p {
                  margin: 0px;
                  padding: 10px 0;
                  display: inline-block;  
                  vertical-align: middle;
                  font-size: 16px;
               }

               .header a {
                 color: white;
               }

              .header img {
                 height: 25px;
              }
  </style>
  <script src="http://cdn.bootcss.com/jquery/3.0.0/jquery.min.js">
  </script>
  <script src="http://nautstatic-10007657.file.myqcloud.com/static/css/readability.min.js" type="text/javascript">
  </script>
  <script type="text/javascript">
   $(document).ready(function() {
                 var loc = document.location;
                 var uri = {
                  spec: "http://dataunion.org/22941.html",
                  host: "http://dataunion.org",
                  prePath: "http://dataunion.org",
                  scheme: "http",
                  pathBase: "http://dataunion.org/"
                 };
    
                 var documentClone = document.cloneNode(true);
                 var article = new Readability(uri, documentClone).parse();
     
                 document.getElementById("xmain").innerHTML = article.content;
                });
  </script>
  <!-- 1466459854: Accept with keywords: (title(0.0):社区,数盟, topn(0.333333333333):社区,数盟,行业资讯,查找,内存,数据挖掘,环上,数据库,例子,键值,文章,余数,数据,节点,路由,机器,字节,算法,缓存数据,服务器,客户端,编程语言,网站,指令,列表,集群,模块,无法,一致性,分布式).-->
 </head>
 <body onload="">
  <div class="header">
   <div class="container">
    <div class="row">
     <div class="col-xs-6 col-sm-6 text-left">
      <a href="/databee">
       <img src="http://nautidea-10007657.cos.myqcloud.com/logo_white.png"/>
      </a>
      <a href="/databee">
       <p>
        数螺
       </p>
      </a>
     </div>
     <div class="hidden-xs col-sm-6 text-right">
      <p>
       致力于数据科学的推广和知识传播
      </p>
     </div>
    </div>
   </div>
  </div>
  <div class="container text-center">
   <h1>
    MemCache 超详细解读
   </h1>
  </div>
  <div class="container" id="xmain">
   ﻿﻿
   <title>
    MemCache 超详细解读 | 数盟社区
   </title>
   <!-- All in One SEO Pack 2.2.7.6.2 by Michael Torbert of Semper Fi Web Design[32,61] -->
   <!-- /all in one seo pack -->
   <!--
<div align="center">
<a href="http://strata.oreilly.com.cn/hadoop-big-data-cn?cmp=mp-data-confreg-home-stcn16_dataunion_pc" target="_blank"><img src="http://dataunion.org/wp-content/uploads/2016/05/stratabj.jpg"/ ></a>
</div>
-->
   <header id="header-web">
    <div class="header-main">
     <hgroup class="logo">
      <h1>
       <a href="http://dataunion.org/" rel="home" title="数盟社区">
        <img src="http://dataunion.org/wp-content/themes/yzipi/images/logo.png"/>
       </a>
      </h1>
     </hgroup>
     <!--logo-->
     <nav class="header-nav">
      <ul class="menu" id="menu-%e4%b8%bb%e8%8f%9c%e5%8d%95">
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-71" id="menu-item-71">
        <a href="http://dataunion.org/category/events" title="events">
         活动
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-22457" id="menu-item-22457">
          <a href="http://dataunion.org/2016timeline">
           2016档期
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-22459" id="menu-item-22459">
          <a href="http://dataunion.org/category/parterc">
           合作会议
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor menu-item-has-children menu-item-20869" id="menu-item-20869">
        <a href="http://dataunion.org/category/tech" title="articles">
         文章
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20867" id="menu-item-20867">
          <a href="http://dataunion.org/category/tech/base" title="base">
           基础架构
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3302" id="menu-item-3302">
          <a href="http://dataunion.org/category/tech/ai" title="ai">
           人工智能
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3303" id="menu-item-3303">
          <a href="http://dataunion.org/category/tech/analysis" title="analysis">
           数据分析
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21920" id="menu-item-21920">
          <a href="http://dataunion.org/category/tech/dm">
           数据挖掘
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3314" id="menu-item-3314">
          <a href="http://dataunion.org/category/tech/viz" title="viz">
           可视化
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-item-3305" id="menu-item-3305">
          <a href="http://dataunion.org/category/tech/devl" title="devl">
           编程语言
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-20876" id="menu-item-20876">
        <a href="http://dataunion.org/category/industry">
         行业
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-16328" id="menu-item-16328">
          <a href="http://dataunion.org/category/industry/case" title="case">
           行业应用
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2112" id="menu-item-2112">
          <a href="http://dataunion.org/category/industry/demo" title="demo">
           Demo展示
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21562" id="menu-item-21562">
          <a href="http://dataunion.org/category/industry/news">
           行业资讯
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-311" id="menu-item-311">
        <a href="http://dataunion.org/category/sources" title="sources">
         资源
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20870" id="menu-item-20870">
        <a href="http://dataunion.org/category/books" title="book">
         图书
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21363" id="menu-item-21363">
        <a href="http://dataunion.org/category/training">
         课程
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-21853" id="menu-item-21853">
        <a href="http://dataunion.org/category/jobs">
         职位
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-22050" id="menu-item-22050">
          <a href="http://dataunion.org/category/career">
           职业规划
          </a>
         </li>
        </ul>
       </li>
      </ul>
     </nav>
     <!--header-nav-->
    </div>
   </header>
   <!--header-web-->
   <div id="main">
    <div id="soutab">
     <form action="http://dataunion.org/" class="search" method="get">
     </form>
    </div>
    <div id="container">
     <nav id="mbx">
      当前位置：
      <a href="http://dataunion.org">
       首页
      </a>
      &gt;
      <a href="http://dataunion.org/category/tech">
       文章
      </a>
      &gt;
      <a href="http://dataunion.org/category/tech/devl">
       编程语言
      </a>
      &gt;  正文
     </nav>
     <!--mbx-->
     <article class="content">
      <header align="centre" class="contenttitle">
       <div class="mscc">
        <h1 class="mscctitle">
         <a href="http://dataunion.org/22941.html">
          MemCache 超详细解读
         </a>
        </h1>
        <address class="msccaddress ">
         <em>
          401 次阅读 -
         </em>
         <a href="http://dataunion.org/category/tech/devl" rel="category tag">
          编程语言
         </a>
        </address>
       </div>
      </header>
      <div class="content-text">
       <p>
        原文链接  http://it.dataguru.cn/article-9069-1.html
       </p>
       <p>
        来源：炼数成金
       </p>
       <p>
        MemCache是什么
       </p>
       <p>
        MemCache是一个自由、源码开放、高性能、分布式的分布式内存对象缓存系统，用于动态Web应用以减轻数据库的负载。它通过在内存中缓存数据和对象来减少读取数据库的次数，从而提高了网站访问的速度。MemCaChe是一个存储键值对的HashMap，在内存中对任意的数据（比如字符串、对象等）所使用的key-value存储，数据可以来自数据库调用、API调用，或者页面渲染的结果。MemCache设计理念就是小而强大，它简单的设计促进了快速部署、易于开发并解决面对大规模的数据缓存的许多难题，而所开放的API使得MemCache能用于Java、C/C++/C#、Perl、Python、PHP、Ruby等大部分流行的程序语言。
       </p>
       <p>
       </p>
       <p>
        另外，说一下MemCache和MemCached的区别：
       </p>
       <p>
       </p>
       <p>
        1、MemCache是项目的名称
       </p>
       <p>
       </p>
       <p>
        2、MemCached是MemCache服务器端可以执行文件的名称
       </p>
       <p>
       </p>
       <p>
        MemCache访问模型
       </p>
       <p>
       </p>
       <p>
        为了加深理解，我模仿着原阿里技术专家李智慧老师《大型网站技术架构 核心原理与案例分析》一书MemCache部分，自己画了一张图：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220745faws9as4tyanahd9.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220745faws9as4tyanahd9.png"/>
        </a>
       </p>
       <p>
        特别澄清一个问题，MemCache虽然被称为”分布式缓存”，但是MemCache本身完全不具备分布式的功能，MemCache集群之间不会相互通信（与之形成对比的，比如JBoss Cache，某台服务器有缓存数据更新时，会通知集群中其他机器更新缓存或清除缓存数据），所谓的”分布式”，完全依赖于客户端程序的实现，就像上面这张图的流程一样。
       </p>
       <p>
       </p>
       <p>
        同时基于这张图，理一下MemCache一次写缓存的流程：
       </p>
       <p>
       </p>
       <p>
        1、应用程序输入需要写缓存的数据
       </p>
       <p>
       </p>
       <p>
        2、API将Key输入路由算法模块，路由算法根据Key和MemCache集群服务器列表得到一台服务器编号
       </p>
       <p>
       </p>
       <p>
        3、由服务器编号得到MemCache及其的ip地址和端口号
       </p>
       <p>
       </p>
       <p>
        4、API调用通信模块和指定编号的服务器通信，将数据写入该服务器，完成一次分布式缓存的写操作
       </p>
       <p>
       </p>
       <p>
        读缓存和写缓存一样，只要使用相同的路由算法和服务器列表，只要应用程序查询的是相同的Key，MemCache客户端总是访问相同的客户端去读取数据，只要服务器中还缓存着该数据，就能保证缓存命中。
       </p>
       <p>
       </p>
       <p>
        这种MemCache集群的方式也是从分区容错性的方面考虑的，假如Node2宕机了，那么Node2上面存储的数据都不可用了，此时由于集群中Node0和Node1还存在，下一次请求Node2中存储的Key值的时候，肯定是没有命中的，这时先从数据库中拿到要缓存的数据，然后路由算法模块根据Key值在Node0和Node1中选取一个节点，把对应的数据放进去，这样下一次就又可以走缓存了，这种集群的做法很好，但是缺点是成本比较大。
       </p>
       <p>
       </p>
       <p>
        一致性Hash算法
       </p>
       <p>
        从上面的图中，可以看出一个很重要的问题，就是对服务器集群的管理，路由算法至关重要，就和负载均衡算法一样，路由算法决定着究竟该访问集群中的哪台服务器，先看一个简单的路由算法。
       </p>
       <p>
       </p>
       <p>
        1、余数Hash
       </p>
       <p>
        比方说，字符串str对应的HashCode是50、服务器的数目是3，取余数得到1，str对应节点Node1，所以路由算法把str路由到Node1服务器上。由于HashCode随机性比较强，所以使用余数Hash路由算法就可以保证缓存数据在整个MemCache服务器集群中有比较均衡的分布。
       </p>
       <p>
       </p>
       <p>
        如果不考虑服务器集群的伸缩性，那么余数Hash算法几乎可以满足绝大多数的缓存路由需求，但是当分布式缓存集群需要扩容的时候，就难办了。
       </p>
       <p>
       </p>
       <p>
        就假设MemCache服务器集群由3台变为4台吧，更改服务器列表，仍然使用余数Hash，50对4的余数是2，对应Node2，但是str原来是存在Node1上的，这就导致了缓存没有命中。如果这么说不够明白，那么不妨举个例子，原来有HashCode为0~19的20个数据，那么：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220745a9ythidzipds98iy.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220745a9ythidzipds98iy.png"/>
        </a>
       </p>
       <p>
        现在我扩容到4台，加粗标红的表示命中：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220745cq5geta9d5tyae1e.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220745cq5geta9d5tyae1e.png"/>
        </a>
       </p>
       <p>
        如果我扩容到20+的台数，只有前三个HashCode对应的Key是命中的，也就是15%。当然这只是个简单例子，现实情况肯定比这个复杂得多，不过足以说明，使用余数Hash的路由算法，在扩容的时候会造成大量的数据无法正确命中（其实不仅仅是无法命中，那些大量的无法命中的数据还在原缓存中在被移除前占据着内存）。这个结果显然是无法接受的，在网站业务中，大部分的业务数据度操作请求上事实上是通过缓存获取的，只有少量读操作会访问数据库，因此数据库的负载能力是以有缓存为前提而设计的。当大部分被缓存了的数据因为服务器扩容而不能正确读取时，这些数据访问的压力就落在了数据库的身上，这将大大超过数据库的负载能力，严重的可能会导致数据库宕机。
       </p>
       <p>
       </p>
       <p>
        这个问题有解决方案，解决步骤为：
       </p>
       <p>
       </p>
       <p>
        （1）在网站访问量低谷，通常是深夜，技术团队加班，扩容、重启服务器
       </p>
       <p>
       </p>
       <p>
        （2）通过模拟请求的方式逐渐预热缓存，使缓存服务器中的数据重新分布
       </p>
       <p>
       </p>
       <p>
        2、一致性Hash算法
       </p>
       <p>
       </p>
       <p>
        一致性Hash算法通过一个叫做一致性Hash环的数据结构实现Key到缓存服务器的Hash映射，看一下我自己画的一张图：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220745yj7ge73igr23ih4k.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220745yj7ge73igr23ih4k.png"/>
        </a>
       </p>
       <p>
        具体算法过程为：先构造一个长度为232的整数环（这个环被称为一致性Hash环），根据节点名称的Hash值（其分布为[0, 232-1]）将缓存服务器节点放置在这个Hash环上，然后根据需要缓存的数据的Key值计算得到其Hash值（其分布也为[0, 232-1]），然后在Hash环上顺时针查找距离这个Key值的Hash值最近的服务器节点，完成Key到服务器的映射查找。
       </p>
       <p>
       </p>
       <p>
        就如同图上所示，三个Node点分别位于Hash环上的三个位置，然后Key值根据其HashCode，在Hash环上有一个固定位置，位置固定下之后，Key就会顺时针去寻找离它最近的一个Node，把数据存储在这个Node的MemCache服务器中。使用Hash环如果加了一个节点会怎么样，看一下：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220746kz5jdpdsejqmobds.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220746kz5jdpdsejqmobds.png"/>
        </a>
       </p>
       <p>
        看到我加了一个Node4节点，只影响到了一个Key值的数据，本来这个Key值应该是在Node1服务器上的，现在要去Node4了。采用一致性Hash算法，的确也会影响到整个集群，但是影响的只是加粗的那一段而已，相比余数Hash算法影响了远超一半的影响率，这种影响要小得多。更重要的是，集群中缓存服务器节点越多，增加节点带来的影响越小，很好理解。换句话说，随着集群规模的增大，继续命中原有缓存数据的概率会越来越大，虽然仍然有小部分数据缓存在服务器中不能被读到，但是这个比例足够小，即使访问数据库，也不会对数据库造成致命的负载压力。
       </p>
       <p>
       </p>
       <p>
        至于具体应用，这个长度为232的一致性Hash环通常使用二叉查找树实现，至于二叉查找树，就是算法的问题了，可以自己去查询相关资料。
       </p>
       <p>
       </p>
       <p>
        MemCache实现原理
       </p>
       <p>
        首先要说明一点，MemCache的数据存放在内存中，存放在内存中个人认为意味着几点：
       </p>
       <p>
       </p>
       <p>
        1、访问数据的速度比传统的关系型数据库要快，因为Oracle、MySQL这些传统的关系型数据库为了保持数据的持久性，数据存放在硬盘中，IO操作速度慢
       </p>
       <p>
       </p>
       <p>
        2、MemCache的数据存放在内存中同时意味着只要MemCache重启了，数据就会消失
       </p>
       <p>
       </p>
       <p>
        3、既然MemCache的数据存放在内存中，那么势必受到机器位数的限制，这个之前的文章写过很多次了，32位机器最多只能使用2GB的内存空间，64位机器可以认为没有上限
       </p>
       <p>
       </p>
       <p>
        然后我们来看一下MemCache的原理，MemCache最重要的莫不是内存分配的内容了，MemCache采用的内存分配方式是固定空间分配，还是自己画一张图说明：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220746v1ep2eef5lkk22ob.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220746v1ep2eef5lkk22ob.png"/>
        </a>
       </p>
       <p>
       </p>
       <p>
        这张图片里面涉及了slab_class、slab、page、chunk四个概念，它们之间的关系是：
       </p>
       <p>
       </p>
       <p>
        1、MemCache将内存空间分为一组slab
       </p>
       <p>
       </p>
       <p>
        2、每个slab下又有若干个page，每个page默认是1M，如果一个slab占用100M内存的话，那么这个slab下应该有100个page
       </p>
       <p>
       </p>
       <p>
        3、每个page里面包含一组chunk，chunk是真正存放数据的地方，同一个slab里面的chunk的大小是固定的
       </p>
       <p>
       </p>
       <p>
        4、有相同大小chunk的slab被组织在一起，称为slab_class
       </p>
       <p>
       </p>
       <p>
        MemCache内存分配的方式称为allocator，slab的数量是有限的，几个、十几个或者几十个，这个和启动参数的配置相关。
       </p>
       <p>
       </p>
       <p>
        MemCache中的value过来存放的地方是由value的大小决定的，value总是会被存放到与chunk大小最接近的一个slab中，比如slab[1]的chunk大小为80字节、slab[2]的chunk大小为100字节、slab[3]的chunk大小为128字节（相邻slab内的chunk基本以1.25为比例进行增长，MemCache启动时可以用-f指定这个比例），那么过来一个88字节的value，这个value将被放到2号slab中。放slab的时候，首先slab要申请内存，申请内存是以page为单位的，所以在放入第一个数据的时候，无论大小为多少，都会有1M大小的page被分配给该slab。申请到page后，slab会将这个page的内存按chunk的大小进行切分，这样就变成了一个chunk数组，最后从这个chunk数组中选择一个用于存储数据。
       </p>
       <p>
       </p>
       <p>
        如果这个slab中没有chunk可以分配了怎么办，如果MemCache启动没有追加-M（禁止LRU，这种情况下内存不够会报Out Of Memory错误），那么MemCache会把这个slab中最近最少使用的chunk中的数据清理掉，然后放上最新的数据。针对MemCache的内存分配及回收算法，总结三点：
       </p>
       <p>
       </p>
       <p>
        1、MemCache的内存分配chunk里面会有内存浪费，88字节的value分配在128字节（紧接着大的用）的chunk中，就损失了30字节，但是这也避免了管理内存碎片的问题
       </p>
       <p>
       </p>
       <p>
        2、MemCache的LRU算法不是针对全局的，是针对slab的
       </p>
       <p>
       </p>
       <p>
        3、应该可以理解为什么MemCache存放的value大小是限制的，因为一个新数据过来，slab会先以page为单位申请一块内存，申请的内存最多就只有1M，所以value大小自然不能大于1M了
       </p>
       <p>
       </p>
       <p>
        再总结MemCache的特性和限制
       </p>
       <p>
        上面已经对于MemCache做了一个比较详细的解读，这里再次总结MemCache的限制和特性：
       </p>
       <p>
       </p>
       <p>
        1、MemCache中可以保存的item数据量是没有限制的，只要内存足够
       </p>
       <p>
       </p>
       <p>
        2、MemCache单进程在32位机中最大使用内存为2G，这个之前的文章提了多次了，64位机则没有限制
       </p>
       <p>
       </p>
       <p>
        3、Key最大为250个字节，超过该长度无法存储
       </p>
       <p>
       </p>
       <p>
        4、单个item最大数据是1MB，超过1MB的数据不予存储
       </p>
       <p>
       </p>
       <p>
        5、MemCache服务端是不安全的，比如已知某个MemCache节点，可以直接telnet过去，并通过flush_all让已经存在的键值对立即失效
       </p>
       <p>
       </p>
       <p>
        6、不能够遍历MemCache中所有的item，因为这个操作的速度相对缓慢且会阻塞其他的操作
       </p>
       <p>
       </p>
       <p>
        7、MemCache的高性能源自于两阶段哈希结构：第一阶段在客户端，通过Hash算法根据Key值算出一个节点；第二阶段在服务端，通过一个内部的Hash算法，查找真正的item并返回给客户端。从实现的角度看，MemCache是一个非阻塞的、基于事件的服务器程序
       </p>
       <p>
       </p>
       <p>
        8、MemCache设置添加某一个Key值的时候，传入expiry为0表示这个Key值永久有效，这个Key值也会在30天之后失效，见memcache.c的源代码：
       </p>
       <p>
       </p>
       <p>
        #define REALTIME_MAXDELTA 60*60*24*30static rel_time_t realtime(const time_t exptime) {       if (exptime == 0) return 0;       if (exptime &gt; REALTIME_MAXDELTA) {
       </p>
       <p>
        if (exptime &lt;= process_started)
       </p>
       <p>
        return (rel_time_t)1;
       </p>
       <p>
        return (rel_time_t)(exptime – process_started);
       </p>
       <p>
        } else {
       </p>
       <p>
        return (rel_time_t)(exptime + current_time);
       </p>
       <p>
        }
       </p>
       <p>
        }
       </p>
       <p>
       </p>
       <p>
        这个失效的时间是memcache源码里面写的，开发者没有办法改变MemCache的Key值失效时间为30天这个限制
       </p>
       <p>
       </p>
       <p>
        MemCache指令汇总
       </p>
       <p>
       </p>
       <p>
        上面说过，已知MemCache的某个节点，直接telnet过去，就可以使用各种命令操作MemCache了，下面看下MemCache有哪几种命令：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220746lnirirrckfolc5n9.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220746lnirirrckfolc5n9.png"/>
        </a>
       </p>
       <p>
       </p>
       <p>
        stats指令解读
       </p>
       <p>
        stats是一个比较重要的指令，用于列出当前MemCache服务器的状态，拿一组数据举个例子：
       </p>
       <p>
       </p>
       <p>
        STAT pid 1023STAT uptime 21069937STAT time 1447235954STAT version 1.4.5STAT pointer_size 64STAT rusage_user 1167.020934STAT rusage_system 3346.933170STAT curr_connections 29STAT total_connections 21STAT connection_structures 49STAT cmd_get 49STAT cmd_set 7458STAT cmd_flush 0STAT get_hits 7401STAT get_misses 57..（delete、incr、decr、cas的hits和misses数，cas还多一个badval）
       </p>
       <p>
        STAT auth_cmds 0STAT auth_errors 0STAT bytes_read 22026555STAT bytes_written 8930466STAT limit_maxbytes 4134304000STAT accepting_conns 1STAT listen_disabled_num 0STAT threads 4STAT bytes 151255336STAT current_items 57146STAT total_items 580656STAT evicitions 0
       </p>
       <p>
       </p>
       <p>
        这些参数反映着MemCache服务器的基本信息，它们的意思是：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220746nkdumm4sms1t5ymm.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220746nkdumm4sms1t5ymm.png"/>
        </a>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220748peqrjvegkkgq22p2.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220748peqrjvegkkgq22p2.png"/>
        </a>
       </p>
       <p>
        stats slab指令解读
       </p>
       <p>
        如果对上面的MemCache存储机制比较理解了，那么我们来看一下各个slab中的信息，还是拿一组数据举个例子：
       </p>
       <p>
       </p>
       <p>
        STAT1:chunk_size 96
       </p>
       <p>
        …
       </p>
       <p>
        STAT 2:chunk_size 144
       </p>
       <p>
        STAT 2:chunks_per_page 7281
       </p>
       <p>
        STAT 2:total_pages 7
       </p>
       <p>
        STAT 2:total_chunks 50967
       </p>
       <p>
        STAT 2:used_chunks 45197
       </p>
       <p>
        STAT 2:free_chunks 1
       </p>
       <p>
        STAT 2:free_chunks_end 5769
       </p>
       <p>
        STAT 2:mem_requested 6084638
       </p>
       <p>
        STAT 2:get_hits 48084
       </p>
       <p>
        STAT 2:cmd_set 59588271
       </p>
       <p>
        STAT 2:delete_hits 0
       </p>
       <p>
        STAT 2:incr_hits 0
       </p>
       <p>
        STAT 2:decr_hits 0
       </p>
       <p>
        STAT 2:cas_hits 0
       </p>
       <p>
        STAT 2:cas_badval 0
       </p>
       <p>
        …
       </p>
       <p>
        STAT 3:chunk_size 216
       </p>
       <p>
        …
       </p>
       <p>
       </p>
       <p>
        首先看到，第二个slab的chunk_size（144）/第一个slab的chunk_size（96）=1.5，第三个slab的chunk_size（216）/第二个slab的chunk_size（144）=1.5，可以确定这个MemCache的增长因子是1.5，chunk_size以1.5倍增长。然后解释下字段的含义：
       </p>
       <p>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/20/220750zo4gc3kzec593sz5.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/20/220750zo4gc3kzec593sz5.png"/>
        </a>
       </p>
       <p>
        看到这个命令的输出量很大，所有信息都很有作用。举个例子吧，比如第一个slab中使用的chunks很少，第二个slab中使用的chunks很多，这时就可以考虑适当增大MemCache的增长因子了，让一部分数据落到第一个slab中去，适当平衡两个slab中的内存，避免空间浪费。
       </p>
       <p>
       </p>
       <p>
        MemCache的Java实现实例
       </p>
       <p>
        讲了这么多，作为一个Java程序员，怎么能不写写MemCache的客户端的实现呢？MemCache的客户端有很多第三方jar包提供了实现，其中比较好的当属XMemCached了，XMemCached具有效率高、IO非阻塞、资源耗费少、支持完整的协议、允许设置节点权重、允许动态增删节点、支持JMX、支持与Spring框架集成、使用连接池、可扩展性好等诸多优点，因而被广泛使用。这里利用XMemCache写一个简单的MemCache客户单实例，也没有验证过，纯属抛砖引玉：
       </p>
       <p>
       </p>
       <p>
        public class MemCacheManager
       </p>
       <p>
        {    private static MemCacheManager instance = new MemCacheManager();
       </p>
       <p>
        /** XMemCache允许开发者通过设置节点权重来调节MemCache的负载，设置的权重越高，该MemCache节点存储的数据越多，负载越大 */
       </p>
       <p>
        private static MemcachedClientBuilder mcb =
       </p>
       <p>
        new XMemcachedClientBuilder(AddrUtil.getAddresses(“127.0.0.1:11211 127.0.0.2:11211 127.0.0.3:11211”), new int[]{1, 3, 5});    private static MemcachedClient mc = null;
       </p>
       <p>
        /** 初始化加载客户端MemCache信息 */
       </p>
       <p>
        static
       </p>
       <p>
        {
       </p>
       <p>
        mcb.setCommandFactory(new BinaryCommandFactory()); // 使用二进制文件
       </p>
       <p>
        mcb.setConnectionPoolSize(10); // 连接池个数，即客户端个数
       </p>
       <p>
        try
       </p>
       <p>
        {
       </p>
       <p>
        mc = mcb.build();
       </p>
       <p>
        }        catch (IOException e)
       </p>
       <p>
        {
       </p>
       <p>
        e.printStackTrace();
       </p>
       <p>
        }
       </p>
       <p>
       </p>
       <p>
        }
       </p>
       <p>
        private MemCacheManager()
       </p>
       <p>
        {
       </p>
       <p>
       </p>
       <p>
        }
       </p>
       <p>
        public MemCacheManager getInstance()
       </p>
       <p>
        {        return instance;
       </p>
       <p>
        }
       </p>
       <p>
        /** 向MemCache服务器设置数据 */
       </p>
       <p>
        public void set(String key, int expiry, Object obj) throws Exception
       </p>
       <p>
        {
       </p>
       <p>
        mc.set(key, expiry, obj);
       </p>
       <p>
        }
       </p>
       <p>
        /** 从MemCache服务器获取数据 */
       </p>
       <p>
        public Object get(String key) throws Exception
       </p>
       <p>
        {        return mc.get(key);
       </p>
       <p>
        }
       </p>
       <p>
        /**
       </p>
       <p>
        * MemCache通过compare and set即cas协议实现原子更新，类似乐观锁，每次请求存储某个数据都要附带一个cas值，MemCache
       </p>
       <p>
        * 比对这个cas值与当前存储数据的cas值是否相等，如果相等就覆盖老数据，如果不相等就认为更新失败，这在并发环境下特别有用     */
       </p>
       <p>
        public boolean update(String key, Integer i) throws Exception
       </p>
       <p>
        {
       </p>
       <p>
        GetsResponse result = mc.gets(key);        long cas = result.getCas();        // 尝试更新key对应的value
       </p>
       <p>
        if (!mc.cas(key, 0, i, cas))
       </p>
       <p>
        {            return false;
       </p>
       <p>
        }        return true;
       </p>
       <p>
        }
       </p>
       <p>
        }
       </p>
      </div>
      <div>
       <strong>
        注：转载文章均来自于公开网络，仅供学习使用，不会用于任何商业用途，如果侵犯到原作者的权益，请您与我们联系删除或者授权事宜，联系邮箱：contact@dataunion.org。转载数盟网站文章请注明原文章作者，否则产生的任何版权纠纷与数盟无关。
       </strong>
      </div>
      <!--content_text-->
      <div class="fenxian">
       <!-- JiaThis Button BEGIN -->
       <div class="jiathis_style_32x32">
        <p class="jiathis_button_weixin">
        </p>
        <p class="jiathis_button_tsina">
        </p>
        <p class="jiathis_button_qzone">
        </p>
        <p class="jiathis_button_cqq">
        </p>
        <p class="jiathis_button_tumblr">
        </p>
        <a class="jiathis jiathis_txt jtico jtico_jiathis" href="http://www.jiathis.com/share" target="_blank">
        </a>
        <p class="jiathis_counter_style">
        </p>
       </div>
       <!-- JiaThis Button END -->
      </div>
     </article>
     <!--content-->
     <!--相关文章-->
     <div class="xianguan">
      <div class="xianguantitle">
       相关文章！
      </div>
      <ul class="pic">
       <li>
        <a href="http://dataunion.org/24678.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/20140917125452915416-216x200.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/24678.html" rel="bookmark" title="python3中的正则模块">
         python3中的正则模块
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/24675.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/t015b337bd75d9ef893-161x200.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/24675.html" rel="bookmark" title="注释是恶魔，请不要再写一行注释">
         注释是恶魔，请不要再写一行注释
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/24660.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/u16130037972892789947fm21gp0-300x157.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/24660.html" rel="bookmark" title="如何从Github上轻松安装R包">
         如何从Github上轻松安装R包
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/24654.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/df53fac99fc53ba5a90666abcca25e6d_b-267x200.png"/>
        </a>
        <a class="link" href="http://dataunion.org/24654.html" rel="bookmark" title="简单形象又有趣地说说强大的神经网络">
         简单形象又有趣地说说强大的神经网络
        </a>
       </li>
      </ul>
     </div>
     <!--相关文章-->
     <div class="comment" id="comments">
      <!-- You can start editing here. -->
      <!-- If comments are open, but there are no comments. -->
      <div class="title">
       期待你一针见血的评论，Come on！
      </div>
      <div id="respond">
       <p>
        不用想啦，马上
        <a href="http://dataunion.org/wp-login.php?redirect_to=http%3A%2F%2Fdataunion.org%2F22941.html">
         "登录"
        </a>
        发表自已的想法.
       </p>
      </div>
     </div>
     <!-- .nav-single -->
    </div>
    <!--Container End-->
    <aside id="sitebar">
     <div class="sitebar_list2">
      <div class="wptag">
       <span class="tagtitle">
        热门标签+
       </span>
       <div class="tagg">
        <ul class="menu" id="menu-%e5%8f%8b%e6%83%85%e9%93%be%e6%8e%a5">
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1605" id="menu-item-1605">
          <a href="http://taidizh.com/">
           泰迪智慧
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-20884" id="menu-item-20884">
          <a href="http://www.transwarp.cn/">
           星环科技
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-3538" id="menu-item-3538">
          <a href="http://datall.org/">
           珈和遥感
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-20888" id="menu-item-20888">
          <a href="http://www.chinahadoop.cn/">
           小象学院
          </a>
         </li>
        </ul>
       </div>
      </div>
     </div>
     <div class="sitebar_list">
      <div class="textwidget">
       <div align="center">
        <a href="http://study.163.com/course/courseMain.htm?courseId=991022" target="_blank">
         <img src="http://dataunion.org/wp-content/uploads/2016/03/dv.jpg"/>
        </a>
       </div>
      </div>
     </div>
     <div class="sitebar_list">
      <h4 class="sitebar_title">
       文章分类
      </h4>
      <div class="tagcloud">
       <a class="tag-link-44" href="http://dataunion.org/category/industry/demo" style="font-size: 10.204724409449pt;" title="4个话题">
        Demo展示
       </a>
       <a class="tag-link-31" href="http://dataunion.org/category/experts" style="font-size: 15.826771653543pt;" title="52个话题">
        专家团队
       </a>
       <a class="tag-link-870" href="http://dataunion.org/category/tech/ai" style="font-size: 19.795275590551pt;" title="273个话题">
        人工智能
       </a>
       <a class="tag-link-488" href="http://dataunion.org/category/%e5%8a%a0%e5%85%a5%e6%95%b0%e7%9b%9f" style="font-size: 8pt;" title="1个话题">
        加入数盟
       </a>
       <a class="tag-link-869" href="http://dataunion.org/category/tech/viz" style="font-size: 17.204724409449pt;" title="93个话题">
        可视化
       </a>
       <a class="tag-link-30" href="http://dataunion.org/category/partners" style="font-size: 10.645669291339pt;" title="5个话题">
        合作伙伴
       </a>
       <a class="tag-link-889" href="http://dataunion.org/category/parterc" style="font-size: 11.582677165354pt;" title="8个话题">
        合作会议
       </a>
       <a class="tag-link-104" href="http://dataunion.org/category/books" style="font-size: 12.96062992126pt;" title="15个话题">
        图书
       </a>
       <a class="tag-link-220" href="http://dataunion.org/category/tech/base" style="font-size: 19.850393700787pt;" title="281个话题">
        基础架构
       </a>
       <a class="tag-link-219" href="http://dataunion.org/category/tech/analysis" style="font-size: 19.409448818898pt;" title="232个话题">
        数据分析
       </a>
       <a class="tag-link-887" href="http://dataunion.org/category/tech/dm" style="font-size: 13.291338582677pt;" title="17个话题">
        数据挖掘
       </a>
       <a class="tag-link-34" href="http://dataunion.org/category/tech" style="font-size: 20.732283464567pt;" title="404个话题">
        文章
       </a>
       <a class="tag-link-1" href="http://dataunion.org/category/uncategorized" style="font-size: 22pt;" title="693个话题">
        未分类
       </a>
       <a class="tag-link-4" href="http://dataunion.org/category/events" style="font-size: 14.503937007874pt;" title="29个话题">
        活动
       </a>
       <a class="tag-link-890" href="http://dataunion.org/category/tech/%e6%b7%b1%e5%ba%a6%e5%ad%a6%e4%b9%a0" style="font-size: 10.204724409449pt;" title="4个话题">
        深度学习
       </a>
       <a class="tag-link-221" href="http://dataunion.org/category/tech/devl" style="font-size: 18.968503937008pt;" title="193个话题">
        编程语言
       </a>
       <a class="tag-link-888" href="http://dataunion.org/category/career" style="font-size: 15.661417322835pt;" title="48个话题">
        职业规划
       </a>
       <a class="tag-link-5" href="http://dataunion.org/category/jobs" style="font-size: 14.11811023622pt;" title="25个话题">
        职位
       </a>
       <a class="tag-link-871" href="http://dataunion.org/category/industry" style="font-size: 15.716535433071pt;" title="49个话题">
        行业
       </a>
       <a class="tag-link-613" href="http://dataunion.org/category/industry/case" style="font-size: 16.984251968504pt;" title="84个话题">
        行业应用
       </a>
       <a class="tag-link-885" href="http://dataunion.org/category/industry/news" style="font-size: 17.425196850394pt;" title="102个话题">
        行业资讯
       </a>
       <a class="tag-link-10" href="http://dataunion.org/category/training" style="font-size: 14.228346456693pt;" title="26个话题">
        课程
       </a>
       <a class="tag-link-16" href="http://dataunion.org/category/sources" style="font-size: 15.661417322835pt;" title="48个话题">
        资源
       </a>
      </div>
     </div>
     <div class="sitebar_list">
      <h4 class="sitebar_title">
       功能
      </h4>
      <ul>
       <li>
        <a href="http://dataunion.org/wp-login.php?action=register">
         注册
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/wp-login.php">
         登录
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/feed">
         文章
         <abbr title="Really Simple Syndication">
          RSS
         </abbr>
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/comments/feed">
         评论
         <abbr title="Really Simple Syndication">
          RSS
         </abbr>
        </a>
       </li>
       <li>
        <a href="https://cn.wordpress.org/" title="基于WordPress，一个优美、先进的个人信息发布平台。">
         WordPress.org
        </a>
       </li>
      </ul>
     </div>
    </aside>
    <div class="clear">
    </div>
   </div>
   <!--main-->
   ﻿
   <footer id="dibu">
    <div class="about">
     <div class="right">
      <ul class="menu" id="menu-%e5%ba%95%e9%83%a8%e8%8f%9c%e5%8d%95">
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-18024" id="menu-item-18024">
        <a href="http://dataunion.org/category/partners">
         合作伙伴
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20881" id="menu-item-20881">
        <a href="http://dataunion.org/contribute">
         文章投稿
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20872" id="menu-item-20872">
        <a href="http://dataunion.org/category/%e5%8a%a0%e5%85%a5%e6%95%b0%e7%9b%9f">
         加入数盟
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-22441" id="menu-item-22441">
        <a href="http://dataunion.org/f-links">
         友情链接
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20874" id="menu-item-20874">
        <a href="http://dataunion.org/aboutus">
         关于数盟
        </a>
       </li>
      </ul>
      <p class="banquan">
       数盟社区        ，
        做最棒的数据科学社区
      </p>
     </div>
     <div class="left">
      <ul class="bottomlist">
       <li>
        <a href="http://weibo.com/DataScientistUnion  " target="_blank" 　title="">
         <img src="http://dataunion.org/wp-content/themes/yzipi/images/weibo.png"/>
        </a>
       </li>
       <li>
        <a class="cd-popup-trigger" href="http://dataunion.org/22941.html#0">
         <img src="http://dataunion.org/wp-content/themes/yzipi/images/weixin.png"/>
        </a>
       </li>
      </ul>
      <div class="cd-popup">
       <div class="cd-popup-container">
        <h1>
         扫描二维码,加微信公众号
        </h1>
        <img src="http://dataunion.org/wp-content/themes/yzipi/images/2014-12-06-1515289049.png"/>
        <a class="cd-popup-close" href="http://dataunion.org/22941.html">
        </a>
       </div>
       <!-- cd-popup-container -->
      </div>
      <!-- cd-popup -->
     </div>
    </div>
    <!--about-->
    <div class="bottom">
     <a href="http://dataunion.org/">
      数盟社区
     </a>
     <a href="http://www.miitbeian.gov.cn/" rel="external nofollow" target="_blank">
      京ICP备14026740号
     </a>
     联系我们：
     <a href="mailto:contact@dataunion.org" target="_blank">
      contact@dataunion.org
     </a>
     <div class="tongji">
     </div>
     <!--bottom-->
     <div class="scroll" id="scroll" style="display:none;">
      ︿
     </div>
    </div>
   </footer>
   <!--dibu-->
  </div>
 </body>
</html>